package com.lemon.tankgame3;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Iterator;
import java.util.Vector;

/**
 * @author 软柠柠吖
 * @date 2022/1/19
 * 坦克大战的绘图区域
 */
// 为了监听 键盘事件，我们要实现KeyListener
// 为了让Panel 不停的重绘子弹，需要将MyPanel 实现Runnable，当做一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {
    // 定义我的坦克
    Hero hero = null;

    // 敌人坦克组
    // 考虑多线程问题 用集合Vector
    Vector<Enemy> enemies = new Vector<>();
    // Enemy[] enemies = new Enemy[3];
    int enemyTankSize = 3;

    // 墙体
    Wall wall = null;

    // 定义一个Vector，用于存放炸弹
    // 说明：当子弹击中坦克时，加入一个Bomb对象到bombs
    Vector<Bomb> bombs = new Vector<>();

    // 定义三张炸弹图片，用于显示爆炸效果
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;
    // 定义一个存放Node 对象的Vector，用于恢复坦克的坐标和方向
    Vector<Node> nodes = new Vector<>();


    public MyPanel(String key) {
        // 先判断记录文件是否存在
        // 如果存在，就正常执行，如果文件不存在，提示，只能开新游戏
        File file = new File(Recorder.getRecordFilePath());
        if ("2".equals(key)) {
            if (file.exists()) {
                nodes = Recorder.getNodesAndHitTankNum();
            } else {
                key = "1";
                System.out.println("记录文件不存在，只能开启新游戏");
            }
        }

        // 墙体
        wall = new Wall(1000, 750);

        // 初始化自己的坦克
        hero = new Hero(500, 450, 0, 0, wall);
        hero.setSpeed(9);

        switch (key) {
            case "1":
                // 初始化敌方坦克
                for (int i = 0; i < enemyTankSize; i++) {
                    enemies.add(new Enemy(100 * (i + 1), 30, 2, 1, wall));
                }
                Enemy.setEnemies(enemies);
                break;
            case "2":
                // 初始化敌方坦克
                for (int i = 0; i < nodes.size(); i++) {
                    enemies.add(new Enemy(nodes.get(i).getX(), nodes.get(i).getY(), nodes.get(i).getDirect(), 1, wall));
                }
                Enemy.setEnemies(enemies);
                break;
            default:
                System.out.println("输入有误");
                break;
        }
        // 初始化图片对象
        image1 = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb_1.gif"));
        image2 = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb_2.gif"));
        image3 = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb_3.gif"));

        // 这里播放指定的音乐
        new AePlayWave("src\\111.wav").start();
    }

    // 编写方法，显示我方击毁敌方坦克的信息
    public void showInfo(Graphics g) {
        // 画出玩家的总成绩
        g.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);

        g.drawString("您累积击毁敌方坦克", 1020, 30);
        // 画出一个敌人坦克
        drawTank(1040, 120, g, 0, 1);

        g.setColor(Color.BLACK);
        g.drawString(String.valueOf(Recorder.getHitTankNum()), 1080, 130);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 游戏区域背景(默认为黑色)
        g.fillRect(0, 0, 1000, 750);
        showInfo(g);

        // 画出坦克-封装方法
        // drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), hero.getType());
        if (hero.isLive()) {
            //activeArea(hero, wall);

            madeTank(hero, g);
        }

        // 如果bombs 集合中有对象，就画出
        for (int i = 0; i < bombs.size(); i++) {
            // 取出炸弹
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Bomb bomb = bombs.get(i);
            // 根据当前这个bomb对象的life值去画出对应的图片
            if (bomb.life > 6) {
                g.drawImage(image1, bomb.x - 30, bomb.y - 30, 60, 60, this);
            } else if (bomb.life > 3) {
                g.drawImage(image2, bomb.x - 30, bomb.y - 30, 60, 60, this);
            } else {
                g.drawImage(image3, bomb.x - 30, bomb.y - 30, 60, 60, this);
            }
            // 让这个炸弹的生命值减少
            bomb.lifeDown();
            // 如果bomb life 为0， 就从bombs 的集合中删除
            if (bomb.life == 0) {
                bombs.remove(bomb);
                i--;
            }
        }


        // 遍历绘制敌方坦克
        for (Enemy enemy : enemies) {
            if (enemy.isLive()) {
                activeArea(enemy, wall);
                // activeArea(enemy, wall);
                madeTank(enemy, g);
            }

            // 遍历绘制子弹
            for (int i = 0; i < enemy.shots.size(); i++) {
                // 取出子弹
                Shot shot = enemy.shots.get(i);
                // 绘制
                if (shot.isLive) {
                    madeBullet(shot, g);
                } else {
                    enemy.shots.remove(shot);
                    i--;
                }
            }

        }

        // 遍历绘制我方坦克子弹
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            if (shot != null && shot.isLive) {
                madeBullet(shot, g);
            } else {
                hero.shots.remove(shot);
            }
        }


    }

    // 绘制坦克
    public void madeTank(Tank tank, Graphics g) {
        drawTank(tank.getX(), tank.getY(), g, tank.getDirect(), tank.getType());
    }

    // 绘制子弹
    public void madeBullet(Shot shot, Graphics g) {
        drawBullet(shot.x, shot.y, g, shot.direct, shot.type);
    }


    public void activeArea(Tank tank, Wall wall) {
        switch (tank.getDirect()) {
            case 0:// 坦克向上
            case 2:// 坦克向下
                if (tank.getX() - 20 < 0) {// 左
                    tank.left = false;
                } else if (tank.getX() + 20 >= wall.x) {// 右
                    tank.right = false;
                }

                if (tank.getY() - 30 < 0) {// 上
                    tank.up = false;
                } else if (tank.getY() + 30 >= wall.y) {// 下
                    tank.down = false;
                }

                break;
            case 1:// 坦克向右
            case 3:// 坦克向左
                if (tank.getX() - 30 < 0) {
                    tank.left = false;
                } else if (tank.getX() + 30 >= wall.x) {
                    tank.right = false;
                }

                if (tank.getY() - 20 < 0) {
                    tank.up = false;
                } else if (tank.getY() + 20 >= wall.y) {
                    tank.down = false;
                }

                break;
            default:
                System.out.println("方向有误");
                break;
        }
    }


    /**
     * 编写方法，画出坦克
     *
     * @param x      坦克左上角x坐标
     * @param y      坦克左上角y坐标
     * @param g      画笔
     * @param direct 坦克方向(上下左右)
     * @param type   坦克类型
     */
    public void drawTank(int x, int y, Graphics g, int direct, int type) {
        switch (type) {
            case 0:
                g.setColor(Color.cyan);
                break;
            case 1:
                g.setColor(Color.yellow);
                break;
            default:
                g.setColor(Color.pink);
                break;
        }

        // 根据坦克方向，来绘制对应形状的坦克
        switch (direct) {
            case 0:// 方向朝上
                // 坦克左轮
                g.fill3DRect(x - 20, y - 30, 10, 60, false);
                // 坦克右轮
                g.fill3DRect(x + 10, y - 30, 10, 60, false);
                // 坦克中间
                g.fill3DRect(x - 10, y - 20, 20, 40, false);
                // 坦克盖子
                g.fillOval(x - 10, y - 10, 20, 20);
                // 炮管
                g.drawLine(x, y - 10, x, y - 35);
                break;
            case 1:// 方向朝右
                // 坦克左轮
                g.fill3DRect(x - 30, y - 20, 60, 10, false);
                // 坦克右轮
                g.fill3DRect(x - 30, y + 10, 60, 10, false);
                // 坦克中间
                g.fill3DRect(x - 20, y - 10, 40, 20, false);
                // 坦克盖子
                g.fillOval(x - 10, y - 10, 20, 20);
                // 炮管
                g.drawLine(x + 10, y, x + 35, y);
                break;
            case 2:// 方向朝下
                // 坦克左轮
                g.fill3DRect(x - 20, y - 30, 10, 60, false);
                // 坦克右轮
                g.fill3DRect(x + 10, y - 30, 10, 60, false);
                // 坦克中间
                g.fill3DRect(x - 10, y - 20, 20, 40, false);
                // 坦克盖子
                g.fillOval(x - 10, y - 10, 20, 20);
                // 炮管
                g.drawLine(x, y + 10, x, y + 35);
                break;
            case 3:// 方向朝左
                // 坦克左轮
                g.fill3DRect(x - 30, y - 20, 60, 10, false);
                // 坦克右轮
                g.fill3DRect(x - 30, y + 10, 60, 10, false);
                // 坦克中间
                g.fill3DRect(x - 20, y - 10, 40, 20, false);
                // 坦克盖子
                g.fillOval(x - 10, y - 10, 20, 20);
                // 炮管
                g.drawLine(x - 10, y, x - 35, y);
                break;
            default:
                break;
        }
    }

    /**
     * 子弹的绘制
     *
     * @param x      子弹横坐标
     * @param y      子弹纵坐标
     * @param g      画笔
     * @param direct 子弹方向
     * @param type   子弹类型
     */
    public void drawBullet(int x, int y, Graphics g, int direct, int type) {
        switch (type) {
            case 0:
                g.setColor(Color.cyan);
                break;
            case 1:
                g.setColor(Color.yellow);
                break;
            default:
                g.setColor(Color.pink);
                break;
        }

        // 根据坦克方向，来绘制对应形状的子弹
        switch (direct) {
            case 0:// 方向朝上
                g.fillRect(x, y, 4, 4);
                break;
            case 1:// 方向朝右
                g.fillRect(x, y, 4, 4);
                break;
            case 2:// 方向朝下
                g.fillRect(x, y, 4, 4);
                break;
            case 3:// 方向朝左
                g.fillRect(x, y, 4, 4);
                break;
            default:
                break;
        }
    }

    // 编写方法，判断我方子弹是否击中敌方坦克
    public void hitTank(Shot shot, Tank tank) {
//        if (!shot.isLive || !tank.isLive()) {
//            return;
//        }
        // 判断shot 击中坦克
        // 这里用了switch 的穿透！！
        switch (tank.getDirect()) {
            case 0:// 坦克向上
            case 2:// 坦克向下
                if (shot.x > tank.getX() - 20 && shot.x < tank.getX() + 20
                        && shot.y > tank.getY() - 30 && shot.y < tank.getY() + 30) {
                    shot.isLive = false;
                    tank.setLive(false);
                    // 当我的子弹击中敌人坦克后，将tank 从集合Vector 中拿掉
                    enemies.remove(tank);
                    // 当我方击毁一个敌方坦克时， 就对数据 hitTankNum++;
                    // 解读：因为 tank 可以是我方坦克，也可以是敌方坦克
                    if (tank instanceof Enemy) {
                        Recorder.addHitTankNum();
                    }
                    // 创建Bomb对象，加入到bombs集合
                    Bomb bomb = new Bomb(tank.getX(), tank.getY());
                    bombs.add(bomb);
                }
                break;
            case 1:// 坦克向右
            case 3:// 坦克向左
                if (shot.x > tank.getX() - 30 && shot.x < tank.getX() + 30
                        && shot.y > tank.getY() - 20 && shot.y < tank.getY() + 20) {
                    shot.isLive = false;

                    tank.setLive(false);
                    enemies.remove(tank);
                    // 当我方击毁一个敌方坦克时， 就对数据 hitTankNum++;
                    // 解读：因为 tank 可以是我方坦克，也可以是敌方坦克
                    if (tank instanceof Enemy) {
                        Recorder.addHitTankNum();
                    }
                    // 创建Bomb对象，加入到bombs集合
                    Bomb bomb = new Bomb(tank.getX(), tank.getY());
                    bombs.add(bomb);
                }
                break;
            default:
                System.out.println("方向有误");
                break;
        }

    }


    @Override
    public void keyTyped(KeyEvent e) {

    }

    // 处理wasd 键按下的情况
    @Override
    public void keyPressed(KeyEvent e) {
//        if (e.getKeyCode() == KeyEvent.VK_S) {// 按下S键 下
//            if (hero.getY() + 30 < wall.y) {
//                hero.setDirect(2);// 改变坦克的方向
//                hero.moveDown();// 坦克向下移动
//            }
//        } else if (e.getKeyCode() == KeyEvent.VK_W) {// 按下W键 上
//            if (hero.getY() - 30 > 0) {
//                hero.setDirect(0);
//                hero.moveUp();
//            }
//        } else if (e.getKeyCode() == KeyEvent.VK_A) {// 按下A键 左
//            if (hero.getX() - 20 > 0) {
//                hero.setDirect(3);
//                hero.moveLeft();
//            }
//        } else if (e.getKeyCode() == KeyEvent.VK_D) {// D键 右
//            if (hero.getX() + 20 < wall.x) {
//                hero.setDirect(1);
//                hero.moveRight();
//            }
//        }
        activeArea(hero, wall);
        if (e.getKeyCode() == KeyEvent.VK_S) {// 按下S键 下
            if (hero.down) {
                hero.setDirect(2);// 改变坦克的方向
                hero.moveDown();// 坦克向下移动
                hero.up = true;
            }
        } else if (e.getKeyCode() == KeyEvent.VK_W) {// 按下W键 上
            if (hero.up) {
                hero.setDirect(0);
                hero.moveUp();
                hero.down = true;
            }
        } else if (e.getKeyCode() == KeyEvent.VK_A) {// 按下A键 左
            if (hero.left) {
                hero.setDirect(3);
                hero.moveLeft();
                hero.right = true;
            }
        } else if (e.getKeyCode() == KeyEvent.VK_D) {// D键 右
            if (hero.right) {
                hero.setDirect(1);
                hero.moveRight();
                hero.left = true;
            }
        }

        // 如果用户按下的是J，就发射
        if (e.getKeyCode() == KeyEvent.VK_J) {
            // System.out.println("发射子弹..");
//            hero.shot·EnemyTank();
            hero.shotTank();


        }

        // 让面板重绘
        repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {// 每隔500ms，重绘区域，刷新绘图区域，子弹就移动
        while (true) {
            // 判断是否有敌方坦克被击中
            for (Shot shot : hero.shots) {
                for (int i = 0; i < enemies.size(); i++) {
                    hitTank(shot, enemies.get(i));
                }
//                for (Enemy enemy : enemies) {
//                    hitTank(shot, enemy);
//                }
            }

            // 判断我方坦克是否被击中
            for (int i = 0; i < enemies.size(); i++) {
                for (int j = 0; j < enemies.get(i).shots.size(); j++) {
                    Shot shot = enemies.get(i).shots.get(j);
                    hitTank(shot, hero);
                }
            }
//            for (Enemy enemy : enemies) {
//                for (int i = 0; i < enemy.shots.size(); i++) {
//                    Shot shot = enemy.shots.get(i);
//                    hitTank(shot, hero);
//                }
//            }
            // 重绘
            repaint();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
